	package com.hp.TrimClient;

import java.io.UnsupportedEncodingException;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

public class SimpleSerializer {

	
	private static RestPath getRestPath(Class<?> objectClass) {
		for (Annotation annotation : objectClass.getAnnotations()) {
			if (annotation instanceof RestPath) {
				return (RestPath)annotation;
			}
		}
		return null;
	}
	
	private static String join(Object[] val, String delimiter) {
		return join(Arrays.asList(val), delimiter);
	}
	
	private static String join(Iterable<?> list, String delimiter) {
		/*String retVal = "";
		for (Object obj : val) {
			if (retVal != "") {
				retVal += delimiter;
			}
			retVal += obj.toString();
		}
		
		return retVal;*/
		
		StringBuilder sb = new StringBuilder();
		   boolean first = true;
		   for (Object item : list)
		   {
		      if (first)
		         first = false;
		      else
		         sb.append(delimiter);
		      sb.append(item.toString());
		   }
		   return sb.toString();
	}
	
	private static String encode(String str) {
		try {
			return java.net.URLEncoder.encode(str,  "UTF-8");
		} catch (UnsupportedEncodingException e) {
			return str;
		}
	}
	
	public static String objectToUrl(Object object) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
		
		
		StringBuilder queryString = new StringBuilder();
		

		RestPath restPath = getRestPath(object.getClass());		

		if (restPath == null) {
			return "/json/syncreply/" + object.getClass().getSimpleName();
		} else {
			List<ArrayList<String>> paths = new ArrayList<ArrayList<String>>();
			
			String[] startPaths = restPath.name();
			Arrays.sort(startPaths, new PathComplexityComparator());
			
			for (String path : startPaths) {
				paths.add(new ArrayList<String>(Arrays.asList(path.split("/"))));
			}
			

			if (!restPath.verb().equals("post")) {
				for (Method method : object.getClass().getMethods()) {
					Boolean inPath = false;
					Annotation dataMember = method.getAnnotation(DataMember.class);
					if(dataMember instanceof DataMember){
						Object val = method.invoke(object);
						
						if (val != null) {			
		
							String key = ((DataMember) dataMember).name();
							
							for(List<String> testPath : paths) {
								int pathIdx = testPath.indexOf("{" + key + "}");
								if (pathIdx > -1) {				
									inPath=true;
									testPath.set(pathIdx, val.toString());
								} 							
							}
							
	
							if (!inPath) {
								if (queryString.length() > 0) {
									queryString.append("&");
								}		
							
								if (val.getClass().isArray()) {				
									queryString.append(key + "=" + join((Object[])val, ","));
								} else if (val instanceof Map<?,?>){
									StringBuilder mapJson = new StringBuilder("{");
									
									for(Object mapKey : ((Map<?,?>)val).keySet()) {
										if (mapJson.length() > 1) {
											mapJson.append(",");
										}
										mapJson.append(mapKey.toString() + ":" + ((Map<?,?>)val).get(mapKey).toString());
									}
									
									mapJson.append("}");
									
									queryString.append(key + "=" + encode(mapJson.toString()));
								} else {
									queryString.append(key + "=" + encode(val.toString()));
								}
								}
						}
					}
				}
			}

			if (queryString.length() > 0) {
				queryString.insert(0, "?");
			}
			
			for(List<String> testPath : paths) {
				
				String newPath = join(testPath, "/");
				
				if (newPath.indexOf("{") < 0) {
					queryString.insert(0, newPath);
					break;
				}
			
			}
		}
		return queryString.toString();			
		
	}
}
